package com.shenghua.logs.operatelogs;

import com.alibaba.fastjson.JSON;
import com.shenghua.dao.mapper.OperateLogMapper;
import com.shenghua.dao.model.OperateLog;
import com.shenghua.dao.model.User;
import com.shenghua.utils.Iptool;
import com.shenghua.utils.MqUtils;
import com.shenghua.utils.sysutil.BeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by Administrator on 2019/4/14.
 */
@Component
@Aspect
public class OperateLogsAspect {
    private Logger logger = LoggerFactory.getLogger(OperateLogsAspect.class);
    private static Integer DATA_LEN = 320;
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Resource
    private MqUtils mqUtils;

    @Around("execution(* *(..)) && @annotation(operateLogsAnnotation)")
    public Object operateLogsAround(ProceedingJoinPoint pjoinPoint, OperateLogsAnnotation operateLogsAnnotation) {
        logger.info("[OperateLogsAspect] operateLogsAround =========>开始切面！");
        OperateLog log = new OperateLog();

        //url client_ip methods consume_time operator
        //operate_time operate_params operate_result type
        //remark described
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        // 请求地址
        log.setUrl(request.getRequestURI());
        // 客户端IP地址
        log.setClientIp(Iptool.getIpAddr(request));
        MethodSignature signature = (MethodSignature) pjoinPoint.getSignature();
        String signatureName = signature.getName();
        String methodName = signature.getDeclaringTypeName() + "." + signatureName;
        // 方法名
        log.setMethods(methodName);
        // 类型add、del、edit、query
        if(null != operateLogsAnnotation.operation()) {
            log.setType(operateLogsAnnotation.operation().type);
        }
        Object result = null;
        long time = 0L;
        long start = System.currentTimeMillis();
        try {
            result = pjoinPoint.proceed();
            long end = System.currentTimeMillis();
            time = end - start;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 耗时
        log.setConsumeTime(new StringBuffer().append(time).append("毫秒").toString());
        User user = (User) request.getSession().getAttribute("userSession");
        // 操作人
        if(null != user) log.setOperator(user.getNickname());
        Object[] paramValues = pjoinPoint.getArgs();
        String[] paramNames = ((MethodSignature) pjoinPoint.getSignature()).getParameterNames();
        Map<String, Object> map = new TreeMap<>();
        for(int i=0; i< paramValues.length; i++) {
            //String typeName = paramValues[i].getClass().getTypeName();
            map.put(paramNames[i], JSON.toJSONString(paramValues[i]));
        }
        // 操作参数
        log.setOperateParams(JSON.toJSONString(map));
        // 操作时间
        log.setOperateTime(new Date());
        // 结果
        if(null != result) {
            String res = JSON.toJSONString(result);
            if(res.length() > DATA_LEN) res = res.substring(0, DATA_LEN-1);
            log.setOperateResult(res);
        }
        //OperateLogMapper operateLogMapper1 = BeanUtils.getBean(OperateLogMapper.class);
        //operateLogMapper.insertSelective(log);
        mqUtils.sendQueueMessage("operateLogs", log);
        //mqUtils.sendTopicMessage("operateLogs", log);
        logger.info("[OperateLogsAspect] operateLogsAround =========>结束切面！");
        return result;
    }
}
